#pragma once

#include "../common/Message.hpp"
#include "../common/Net.hpp"
#include "Requester.hpp"

namespace rpc
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallback = std::function<void(const Json::Value&)>;
            RpcCaller(Requester::ptr req) : _requester(req)
            {
            }
            // Requester在BaseMessage层做处理
            // RpcCaller是为了得到result
            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, 
                Json::Value &result)
            {
                DLOG("rpc request sync start");
                // 1. 构造Rpc请求
                RpcRequest::ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMsgType(MSG_TYPE::REQ_RPC);
                req->setMethod(method);
                req->setParams(params);

                // 2. 发送Rpc请求
                BaseMessage::ptr base_rsp;
                BaseMessage::ptr base_req = std::dynamic_pointer_cast<BaseMessage>(req);
                bool n = _requester->send(conn, base_req, base_rsp);
                if (n == false)
                {
                    ELOG("rpc request sync failed");
                    return false;
                }
                DLOG("receive and analyze");

                // 3. 校验
                RpcResponse::ptr rpc_rsp = std::dynamic_pointer_cast<RpcResponse>(base_rsp);
                if (rpc_rsp.get() == nullptr)
                {
                    ELOG("rpc request type conversion failed");
                    return false;
                }

                if (rpc_rsp->rcode() != RCODE::RCODE_OK)
                {
                    ELOG("rpc request error");
                    return false;
                }

                // 4. 设置结果
                result = rpc_rsp->result();
                DLOG("set the result");
                return true;
            }

            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, 
                JsonAsyncResponse &resp)
            {
                // 1. 构造Rpc请求
                RpcRequest::ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMsgType(MSG_TYPE::REQ_RPC);
                req->setMethod(method);
                req->setParams(params);

                // 2. 发送请求
                // 3. 相应检验
                // 4，获取结果
                BaseMessage::ptr base_rsp;
                BaseMessage::ptr base_req = std::dynamic_pointer_cast<BaseMessage>(req);
                std::shared_ptr<std::promise<Json::Value>> promise = std::make_shared<std::promise<Json::Value>>();
                resp = promise->get_future(); // 关联
                Requester::RequestCallback cb = std::bind(&RpcCaller::callbackAsync, this, promise, std::placeholders::_1);

                bool n = _requester->send(conn, base_req, cb);
                if (n == false)
                {
                    ELOG("rpc request async failed");
                    return false;
                }
                return true;
            }

            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, 
                const JsonResponseCallback &cb) 
            {
                // 1. 构造Rpc请求
                RpcRequest::ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMsgType(MSG_TYPE::REQ_RPC);
                req->setMethod(method);
                req->setParams(params);

                // 2. 发送请求
                // 3. 相应检验
                // 4，获取结果
                BaseMessage::ptr base_rsp;
                BaseMessage::ptr base_req = std::dynamic_pointer_cast<BaseMessage>(req);
                Requester::RequestCallback callback = std::bind(&RpcCaller::callback, this, cb, std::placeholders::_1);
                bool n = _requester->send(conn, base_req, callback);
                if (n == false)
                {
                    ELOG("rpc request async failed");
                    return false;
                }
                return true;
            }

        private:
            void callbackAsync(std::shared_ptr<std::promise<Json::Value>> &promise, BaseMessage::ptr &rsp) // 设置回调
            {
                // 校验 
                RpcResponse::ptr rpc_rsp = std::dynamic_pointer_cast<RpcResponse>(rsp);
                if (rpc_rsp.get() == nullptr)
                {
                    ELOG("rpc request type conversion failed");
                    return;
                }

                if (rpc_rsp->rcode() != RCODE::RCODE_OK)
                {
                    ELOG("rpc request error");
                    return;
                }
                // 设置结果
                promise->set_value(rpc_rsp->result());
            }

            void callback(const JsonResponseCallback &cb, BaseMessage::ptr &rsp)
            {
                // 校验
                RpcResponse::ptr rpc_rsp = std::dynamic_pointer_cast<RpcResponse>(rsp);
                if (rpc_rsp.get() == nullptr)
                {
                    ELOG("rpc request type conversion failed");
                    return;
                }

                if (rpc_rsp->rcode() != RCODE::RCODE_OK)
                {
                    ELOG("rpc request error");
                    return;
                }

                // 执行回调
                cb(rpc_rsp->result());
            }

        private:
            Requester::ptr _requester; // 通过Requester::send发送请求
        };
    }
}